﻿// <copyright file="Square.cs" company="Ecole Normale Supérieure">
// Released under GPLv2
// </copyright>
// <summary>Contains the square class.</summary>

namespace Sqwarea.Persistence
{
    using System;
    using System.Drawing;
    using System.Runtime.Serialization;

    /// <summary>
    /// This class represents a square in the map.
    /// </summary>
    [DataContract]
    public class Square : ICloneable
    {
        /// <summary>
        /// Default troops number
        /// </summary>
        public const int DefaultTroopsNumber = 10;

        /// <summary>
        /// Initializes a new instance of the Square class. Create a default square belonging to neutral player
        /// </summary>
        /// <param name="position">position of the new square</param>
        public Square(Point position)
        {
            KingId = King.NeutralKingId;
            Position = position;
            Troops = Square.DefaultTroopsNumber;
            HasKing = false;
            PathToKing = Direction.North;
        }

        /// <summary>
        /// Initializes a new instance of the Square class.
        /// </summary>
        /// <param name="position">position of the new square</param>
        /// <param name="kingId">kingId of the owner of the square</param>
        /// <param name="troops">number of units on the square</param>
        /// <param name="hasKing">whether or not the king is on the square</param>
        public Square(Point position, long kingId, int troops, bool hasKing)
        {
            KingId = kingId;
            Position = position;
            Troops = troops;
            HasKing = hasKing;
            PathToKing = Direction.North;
        }

        /// <summary>
        /// Gets or sets ETag of the square.
        /// This is not serialized, it's an information in CloudEntity.
        /// Used to update only required square in Web Role.
        /// If not supported (ex. : mock), it's equal to null and the quare is considered as modified.
        /// </summary>
        public string ETag { get; set; }

        /// <summary>
        /// Gets or sets king's id. This can be used for transferring information of the king.
        /// When the square is neutral, it should be 0.
        /// </summary>
        [DataMember]
        public long KingId { get; set; }

        /// <summary>
        /// Gets the coordinates of this square.
        /// </summary>
        [DataMember]
        public Point Position { get; private set;  }

        /// <summary>
        /// Gets or sets the number of troops in this square. This can be used for gui output and calculation on attacks.
        /// </summary>
        [DataMember]
        public int Troops { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this square contains a king. This can be used when the square is invaded for judging if the whole empire is brought down.
        /// </summary>
        [DataMember]
        public bool HasKing { get; set; }

        /// <summary>
        /// Gets or sets the direction of a path to the king
        /// Unspecified if the case is neutral or if a king is on it
        /// This property is for connexity
        /// </summary>
        [DataMember]
        public Direction PathToKing { get; set; }

        /// <summary>
        /// Clones the square
        /// </summary>
        /// <returns>A new square with exactly the same fields</returns>
        public object Clone()
        {
            Square clone = new Square(Position, KingId, Troops, HasKing);
            clone.PathToKing = PathToKing;
            clone.ETag = ETag;
            return clone;
        }

        /// <summary>
        /// Override Equals to do a field by field comparison
        /// </summary>
        /// <param name="obj">the square to be compared to</param>
        /// <returns>True iff there is equality for all fields</returns>
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return base.Equals(obj);
            }

            var otherSquare = (Square) obj;
            return otherSquare.ETag == ETag &&
                   otherSquare.HasKing == HasKing &&
                   otherSquare.KingId == KingId &&
                   otherSquare.PathToKing == PathToKing &&
                   otherSquare.Position == Position &&
                   otherSquare.Troops == Troops;
        }
    }
}
